//Entry.cpp
//This cpp file deals with creation and adjustment of Entry, be it Task of Event
//@author A0101038Y
//@class Entry
#include "Entry.h"

QDate Entry::getDate() {
	if(getStartDate().isValid()){
		return getStartDate();
	} else if(getEndDate().isValid()) {
		return getEndDate();
	} else return QDate();
}
Entry::~Entry(void)
{
}
Entry::Entry(string name, string date, string time):_name(name)
{
	_endDate=QDate::fromString(QString::fromStdString(date), FORMAT_DATE_INPUT);
	_endTime=QTime::fromString(QString::fromStdString(time), FORMAT_TIME);
}
Entry::Entry(string name, QDate endDate, QTime endTime) : _name(name), _endDate(endDate), _endTime(endTime)
{
}
Entry::Entry() {
}
//Entry::~Entry(void)
//{
//}
void Entry::setName(string name) {
	 _name = name;
}
void Entry::setEndDate(QDate endDate, CommonEnum::CALLER caller) {
	//Setting of End Date for new entry and for editted entry. 
	if(isFloat()) {
		setFloatEndDate(endDate, caller);
	}
	QDate oldDate = _endDate;
	_endDate = endDate;
	QTime oldTime = getEndTime();
	//validation of Start and End Date. Only available for editing of date.
	if(caller != CommonEnum::CALLER_TOKENISER){
		if(getEntryType()==TYPE_EVENT){
			if(getEndTime().isValid()){
				correctEndDateTimeValid(caller, oldDate, oldTime);
			} else{
				_endTime = getStartTime();
				oldTime = _endTime;
				correctEndDateTimeValid(caller, oldDate, oldTime);
			}
		}
	}
}
void Entry::setEndTime(QTime endTime, CommonEnum::CALLER caller) {
	//setting of end time for new and edited entry
	if(isFloat()) {
		//set a default end date and time for a floating event.
		setFloatEndTime(endTime, caller);
	}
	QTime oldTime = _endTime;
	_endTime=endTime;
	QDate oldDate = getEndDate();
	//validation of Start and End Time. Only available for editing of date.
	if(caller != CommonEnum::CALLER_TOKENISER){
		if(getEntryType()==TYPE_EVENT){
			if(getEndDate().isValid()){
				correctEndDateTimeValid(caller, oldDate, oldTime);
			} else{
				_endDate = getStartDate();
				oldDate = _endDate;
				correctEndDateTimeValid(caller, oldDate, oldTime);
			}
		}
	}
}
bool Entry::isFloat() const{
	return (!getStartDate().isValid() && !getStartTime().isValid() && !getEndDate().isValid() && !getEndTime().isValid());
}
bool Entry::isEmpty() {
	return(_name == EMPTY_STRING);// && _endDate = EMPTY_DATE && _endTime = EMPTY_TIME);
}
QDate Entry::getEndDate() const {
	return _endDate;
}
QTime Entry::getEndTime() const {
	return _endTime;
}
string Entry::getName() const {
	return _name;
}
bool Entry::isPast(QDateTime target) const {
	if(getEndDate().isValid() && getEndTime().isValid()) {//valid endatetime
		return QDateTime(getEndDate(), getEndTime()) < target;//return if ended
	} else {
		return false;
	}
}
bool Entry::isSpanning() const {
	if(getStartDate().isValid() && getEndDate().isValid()){
		return (getStartDate() != getEndDate());
	}
	return false;
}
bool Entry::isOccuring(QDate target) const{
	if (getStartDate().isValid() && getEndDate().isValid()){
		if(target >= getStartDate() && target <= getEndDate()){//starts and ends today, starts before today
			return true;
		} else{
			return false;
		}
	} else {
		if (getStartDate().isValid()){  //if only Start Date is valid.
			if(target == getStartDate()){
				return true;
			} else {
				return false;
			}
		} else {
			if (getEndDate().isValid()){  //if only End Date is valid.
				if(target == getEndDate()){
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
	}
}
void Entry::correctEndDateTimeValid(CommonEnum::CALLER caller, QDate oldDate, QTime oldTime){
	//function correct invalid edit where end date or time is earlier than start date or time (for end date or time edit).
	if(getStartDate().isValid() && getStartTime().isValid() && getEndDate().isValid() && getEndTime().isValid()){ 	//do nothing when any date or time is not valid.
		QDate startDate = getStartDate();
		QTime startTime = getStartTime();
		QDate endDate = getEndDate();
		QTime endTime = getEndTime();
		QDateTime startDateTime (startDate, startTime);
		QDateTime endDateTime (endDate, endTime);
		if(caller == CommonEnum::CALLER_ENTRIESMANAGER){//validate only items from Entriesmanager. 
			if(!isStartEndDateTimeValid(startDateTime, endDateTime)){ 
				revertInvalidEditDateTime(oldDate, oldTime); //revert changes made in setEndDate and setEndTime.
				throw BotException(BotException::EXCEPTION_START_END_CONFLICT); //throw exception when end is earlier than start.
			} else {
				return;
			}
		} else {
			return;
		}
	}
}
void Entry::revertInvalidEditDateTime(QDate oldDate, QTime oldTime){
	//revert changes made previously in setDate or setTime function (for end date or end time edit)
	_endDate = oldDate;
	_endTime = oldTime;
}
bool Entry::isStartEndDateTimeValid(QDateTime startDateTime, QDateTime endDateTime){
	//check function to ensure start date and time is earlier than end date or time
	if(startDateTime <= endDateTime){
		return true;
	} else {
		return false;
	}
}
const QDate Entry::EMPTY_DATE = QDate();
const QTime Entry::EMPTY_TIME = QTime();
const string Entry::EMPTY_STRING="";
const QString Entry::FORMAT_DATE = "ddMMyyyy";
const QString Entry::FORMAT_DATE_INPUT = "dd/MM/yy";
const QString Entry::FORMAT_TIME = "hhmm";
const string Entry::TYPE_EVENT = "EVENT";